package com.treeman.api.controller;

import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import com.treeman.api.ApiRequestError;
import com.treeman.api.ApiRequestError.ApiError;

@Controller
public abstract class ApiExceptionResolverController {

	private static Logger log = Logger
			.getLogger(ApiExceptionResolverController.class);

	@Autowired
	private MessageSource messageSource;

	@ExceptionHandler(AccessDeniedException.class)
	public @ResponseBody
	ApiRequestError handleAccessDeniedException(AccessDeniedException e,
			HttpServletRequest request, HttpServletResponse response,
			Locale locale) {
		log.debug("AccessDeniedException handled: " + e.getLocalizedMessage());

		if (SecurityContextHolder.getContext().getAuthentication() instanceof AnonymousAuthenticationToken) {
			log.debug("User is not logged in");
			response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

			String errorMessage = messageSource.getMessage(
					"request.error.unauthorized", null, locale);

			return new ApiRequestError(ApiError.NOT_LOGGED, errorMessage);
		} else {
			log.info("User "
					+ SecurityContextHolder.getContext().getAuthentication()
							.getName() + " has no permission. Request url: "
					+ request.getRequestURL());
			response.setStatus(HttpServletResponse.SC_FORBIDDEN);

			String errorMessage = messageSource.getMessage(
					"request.error.forbidden", null, locale);

			return new ApiRequestError(ApiError.NO_PERMISSION, errorMessage);
		}
	}

	@ExceptionHandler(MissingServletRequestParameterException.class)
	@ResponseStatus(value = HttpStatus.BAD_REQUEST)
	public @ResponseBody
	ApiRequestError handleMissingServletRequestParameterException(
			MissingServletRequestParameterException e) {
		log.warn("MissingServletRequestParameterException: "
				+ e.getLocalizedMessage());
		return new ApiRequestError(ApiError.MISSING_REQUEST_PARAMS,
				e.getLocalizedMessage());
	}

	@ExceptionHandler(Exception.class)
	@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
	public @ResponseBody
	ApiRequestError handleException(Exception e) {
		log.warn("Exception: " + e.getLocalizedMessage());
		e.printStackTrace();
		return new ApiRequestError(ApiError.INTERNAL_ERROR, "Internal error");
	}
}
